package parser;

import com.github.javaparser.ParseException;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.type.TypeParameter;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import entity.MethodEntity;
import entity.VariableEntity;
import type.AccessModifierEnum;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MethodParser {
    public static MethodEntity createMethodEntity(JavaMethod jm) throws IOException, ParseException {
        MethodEntity entity = null;
        if (jm != null) {
            entity = new MethodEntity();
            entity.setName(jm.getName());
            entity.setCode(jm.getCodeBlock());
            entity.setAccessModifierEnum(getAccessModifier(jm));
            entity.setDeclarationClass(jm.getDeclaringClass());
            entity.setArguments(getArguments(jm));
            entity.setCalledMethods(getCalledMethods(jm));
            entity.setFinal(jm.isFinal());
            entity.setStatic(jm.isStatic());
            entity.setAbstract(jm.isAbstract());
            entity.setSynchronized(jm.isSynchronized());
            entity.setStrictfp(jm.isStrictfp());
            entity.setNative(jm.isNative());
            entity.setTypeParameters(getTypeParameters(jm));
            entity.setReturns(jm.getReturns());
        }

        return entity;
    }

    /**
     * 泛型声明/类型参数
     */
    public static List<TypeParameter> getTypeParameters(JavaMethod jm) {
        MethodDeclaration declaration = getMethodDeclaration(jm.getCodeBlock());
        if (declaration != null) {
            return declaration.getTypeParameters();
        }
        return null;
    }

    /**
     * 使用 JavaParser 获取方法对象
     */
    public static MethodDeclaration getMethodDeclaration(String code) {
        return StaticJavaParser.parseMethodDeclaration(code);
    }

    /**
     * 获取方法调用列表
     */
    public static List<MethodCallExpr> getCalledMethods(JavaMethod jm) {
        return getMethodDeclaration(jm.getCodeBlock()).findAll(MethodCallExpr.class);
    }

    /**
     * 获取参数列表
     */
    public static List<VariableEntity> getArguments(JavaMethod jm) throws IOException, ParseException {
        List<VariableEntity> arguments = null;
        List<JavaParameter> parameters = jm.getParameters();
        if (parameters != null && !parameters.isEmpty()) {
            arguments = new ArrayList<>();
            for (JavaParameter jp : parameters) {
                arguments.add(VariableParser.createVariableEntity(jp));
            }
        }
        return arguments;
    }

    /**
     * 获取访问修饰符
     */
    public static AccessModifierEnum getAccessModifier(JavaMethod jm) {
        if (jm.isPublic()) {
            return AccessModifierEnum.PUBLIC;
        } else if (jm.isPrivate()) {
            return AccessModifierEnum.PRIVATE;
        } else if (jm.isProtected()) {
            return AccessModifierEnum.PROTECTED;
        } else {
            return AccessModifierEnum.DEFAULT;
        }
    }
}
